home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / MATH.SWG / 0050_Nice Expression Parser.pas < prev    next >
Pascal/Delphi Source File  |  1993-11-26  |  5KB  |  198 lines

  1. PROGRAM Expr;
  2.  
  3. {
  4.   Simple recursive expression parser based on the TCALC example of TP3.
  5.   Written by Lars Fosdal 1987
  6.   Released to the public domain 1993
  7. }
  8.  
  9. PROCEDURE Eval(Formula : String;    { Expression to be evaluated}
  10.                VAR Value   : Real;      { Return value }
  11.                VAR ErrPos  : Integer);  { error position }
  12.   CONST
  13.     Digit: Set of Char = ['0'..'9'];
  14.   VAR
  15.     Posn  : Integer;   { Current position in Formula}
  16.     CurrChar   : Char;      { character at Posn in Formula }
  17.  
  18.  
  19. PROCEDURE ParseNext; { returnerer neste tegn i Formulaen  }
  20. BEGIN
  21.   REPEAT
  22.     Posn:=Posn+1;
  23.     IF Posn<=Length(Formula) THEN CurrChar:=Formula[Posn]
  24.      ELSE CurrChar:=^M;
  25.   UNTIL CurrChar<>' ';
  26. END  { ParseNext };
  27.  
  28.  
  29. FUNCTION add_subt: Real;
  30.   VAR
  31.     E   : Real;
  32.     Opr : Char;
  33.  
  34.   FUNCTION mult_DIV: Real;
  35.     VAR
  36.       S   : Real;
  37.       Opr : Char;
  38.  
  39.     FUNCTION Power: Real;
  40.       VAR
  41.         T : Real;
  42.  
  43.       FUNCTION SignedOp: Real;
  44.  
  45.         FUNCTION UnsignedOp: Real;
  46.           TYPE
  47.             StdFunc = (fabs,    fsqrt, fsqr, fsin, fcos,
  48.                        farctan, fln,   flog, fexp, ffact);
  49.             StdFuncList = ARRAY[StdFunc] of String[6];
  50.  
  51.           CONST
  52.             StdFuncName: StdFuncList =
  53.             ('ABS','SQRT','SQR','SIN','COS',
  54.             'ARCTAN','LN','LOG','EXP','FACT');
  55.           VAR
  56.             E, L, Start    : Integer;
  57.             Funnet         : Boolean;
  58.             F              : Real;
  59.             Sf             : StdFunc;
  60.  
  61.               FUNCTION Fact(I: Integer): Real;
  62.               BEGIN
  63.                 IF I > 0 THEN BEGIN Fact:=I*Fact(I-1); END
  64.                 ELSE Fact:=1;
  65.               END  { Fact };
  66.  
  67.           BEGIN { FUNCTION UnsignedOp }
  68.             IF CurrChar in Digit THEN
  69.             BEGIN
  70.               Start:=Posn;
  71.               REPEAT ParseNext UNTIL not (CurrChar in Digit);
  72.               IF CurrChar='.' THEN REPEAT ParseNext UNTIL not (CurrChar in Digit);
  73.               IF CurrChar='E' THEN
  74.               BEGIN
  75.                 ParseNext;
  76.                 REPEAT ParseNext UNTIL not (CurrChar in Digit);
  77.               END;
  78.               Val(Copy(Formula,Start,Posn-Start),F,ErrPos);
  79.             END ELSE
  80.             IF CurrChar='(' THEN
  81.             BEGIN
  82.               ParseNext;
  83.               F:=add_subt;
  84.               IF CurrChar=')' THEN ParseNext ELSE ErrPos:=Posn;
  85.             END ELSE
  86.             BEGIN
  87.               Funnet:=False;
  88.               FOR sf:=fabs TO ffact DO
  89.               IF not Funnet THEN
  90.               BEGIN
  91.                 l:=Length(StdFuncName[sf]);
  92.                 IF Copy(Formula,Posn,l)=StdFuncName[sf] THEN
  93.                 BEGIN
  94.                   Posn:=Posn+l-1; ParseNext;
  95.                   f:=UnsignedOp;
  96.                   CASE sf of
  97.                     fabs:     f:=abs(f);
  98.                     fsqrt:    f:=SqrT(f);
  99.                     fsqr:     f:=Sqr(f);
  100.                     fsin:     f:=Sin(f);
  101.                     fcos:     f:=Cos(f);
  102.                     farctan:  f:=ArcTan(f);
  103.                     fln :     f:=LN(f);
  104.                     flog:     f:=LN(f)/LN(10);
  105.                     fexp:     f:=EXP(f);
  106.                     ffact:    f:=fact(Trunc(f));
  107.                   END;
  108.                   Funnet:=True;
  109.                 END;
  110.               END;
  111.               IF not Funnet THEN
  112.               BEGIN
  113.                 ErrPos:=Posn;
  114.                 f:=0;
  115.               END;
  116.             END;
  117.             UnsignedOp:=F;
  118.           END { UnsignedOp};
  119.  
  120.         BEGIN { SignedOp }
  121.           IF CurrChar='-' THEN
  122.           BEGIN
  123.             ParseNext; SignedOp:=-UnsignedOp;
  124.           END ELSE SignedOp:=UnsignedOp;
  125.         END { SignedOp };
  126.  
  127.       BEGIN { Power }
  128.         T:=SignedOp;
  129.         WHILE CurrChar='^' DO
  130.         BEGIN
  131.           ParseNext;
  132.           IF t<>0 THEN t:=EXP(LN(abs(t))*SignedOp) ELSE t:=0;
  133.         END;
  134.         Power:=t;
  135.       END { Power };
  136.  
  137.  
  138.     BEGIN { mult_DIV }
  139.       s:=Power;
  140.       WHILE CurrChar in ['*','/'] DO
  141.       BEGIN
  142.         Opr:=CurrChar; ParseNext;
  143.         CASE Opr of
  144.           '*': s:=s*Power;
  145.           '/': s:=s/Power;
  146.         END;
  147.       END;
  148.       mult_DIV:=s;
  149.     END { mult_DIV };
  150.  
  151.   BEGIN { add_subt }
  152.     E:=mult_DIV;
  153.     WHILE CurrChar in ['+','-'] DO
  154.     BEGIN
  155.       Opr:=CurrChar; ParseNext;
  156.       CASE Opr of
  157.         '+': e:=e+mult_DIV;
  158.         '-': e:=e-mult_DIV;
  159.       END;
  160.     END;
  161.     add_subt:=E;
  162.   END { add_subt };
  163.  
  164. BEGIN {PROC Eval}
  165.   IF Formula[1]='.'
  166.   THEN Formula:='0'+Formula;
  167.   IF Formula[1]='+'
  168.   THEN Delete(Formula,1,1);
  169.   FOR Posn:=1 TO Length(Formula)
  170.   DO Formula[Posn] := Upcase(Formula[Posn]);
  171.   Posn:=0;
  172.   ParseNext;
  173.   Value:=add_subt;
  174.   IF CurrChar=^M THEN ErrPos:=0 ELSE ErrPos:=Posn;
  175. END {PROC Eval};
  176.  
  177. VAR
  178.   Formula : String;
  179.   Value   : Real;
  180.   i, Err  : Integer;
  181. BEGIN
  182.   REPEAT
  183.     Writeln;
  184.     Write('Enter formula (empty exits): '); Readln(Formula);
  185.     IF Formula='' THEN Exit;
  186.     Eval(Formula, Value, Err);
  187.     Write(Formula);
  188.     IF Err=0
  189.     THEN Writeln(' = ',Value:0:5)
  190.     ELSE BEGIN
  191.       Writeln;
  192.       FOR i:=1 TO Err-1 DO Write(' ');
  193.       Writeln('^-- Error in formula');
  194.     END;
  195.   UNTIL False;
  196. END.
  197.  
  198.